home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / GLUT / progs / examples / surfgrid.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  16KB  |  591 lines

  1. /**
  2.  * surfgrid.c - simple test of polygon offset
  3.  *
  4.  * GLUT distribution version  $Revision: 1.2 $
  5.  *
  6.  * usage:
  7.  *    surfgrid [-f]
  8.  *
  9.  * options:
  10.  *    -f    run on full screen
  11.  *
  12.  * keys:
  13.  *    p    toggle polygon offset
  14.  *      F       increase polygon offset factor
  15.  *      f       decrease polygon offset factor
  16.  *      B       increase polygon offset bias
  17.  *      b       decrease polygon offset bias
  18.  *    g    toggle grid drawing
  19.  *    s    toggle smooth/flat shading
  20.  *    n    toggle whether to use GL evaluators or GLU nurbs
  21.  *    u    decr number of segments in U direction
  22.  *    U    incr number of segments in U direction
  23.  *    v    decr number of segments in V direction
  24.  *    V    incr number of segments in V direction
  25.  *    escape    quit
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <stdlib.h>
  31. #include <math.h>
  32. #include <GL/glut.h>
  33.  
  34. #define W 600
  35. #define H 600
  36.  
  37. float z_axis[] = { 0.0, 0.0, 1.0 };
  38.  
  39. void 
  40. norm(float v[3])
  41. {
  42.   float r;
  43.  
  44.   r = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
  45.  
  46.   v[0] /= r;
  47.   v[1] /= r;
  48.   v[2] /= r;
  49. }
  50.  
  51. void 
  52. cross(float v1[3], float v2[3], float result[3])
  53. {
  54.   result[0] = v1[1] * v2[2] - v1[2] * v2[1];
  55.   result[1] = v1[2] * v2[0] - v1[0] * v2[2];
  56.   result[2] = v1[0] * v2[1] - v1[1] * v2[0];
  57. }
  58.  
  59. float 
  60. length(float v[3])
  61. {
  62.   float r = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
  63.   return r;
  64. }
  65.  
  66. static long winwidth = W, winheight = H;
  67. GLUnurbsObj *nobj;
  68. GLuint surflist, gridlist;
  69.  
  70. int useglunurbs = 0;
  71. int smooth = 1;
  72. GLboolean tracking = GL_FALSE;
  73. int showgrid = 1;
  74. int showsurf = 1;
  75. int fullscreen = 0;
  76. float modelmatrix[16];
  77. float factor = 0.5;
  78. float bias = 0.002;
  79. int usegments = 4;
  80. int vsegments = 4;
  81.  
  82. int spindx, spindy;
  83. int startx, starty;
  84. int curx, cury;
  85. int prevx, prevy;       /* to get good deltas using glut */
  86.  
  87. void redraw(void);
  88. void createlists(void);
  89.  
  90. /* Control points of the torus in Bezier form.  Can be rendered
  91.    using OpenGL evaluators. */
  92. static GLfloat torusbezierpts[] =
  93. {
  94. /* *INDENT-OFF* */
  95.    4.0, 0.0, 0.0, 4.0, 2.0, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0,
  96.    3.0, 0.0, 1.0, 2.0, 4.0, 0.0, 1.0, 2.0, 8.0, 0.0, 0.0, 4.0,
  97.    8.0, 0.0, 0.0, 4.0, 4.0, 0.0,-1.0, 2.0, 3.0, 0.0,-1.0, 2.0,
  98.    3.0, 0.0,-1.0, 2.0, 2.0, 0.0,-1.0, 2.0, 4.0, 0.0, 0.0, 4.0,
  99.    2.0,-2.0, 0.0, 2.0, 1.0,-1.0, 0.5, 1.0, 1.5,-1.5, 0.5, 1.0,
  100.    1.5,-1.5, 0.5, 1.0, 2.0,-2.0, 0.5, 1.0, 4.0,-4.0, 0.0, 2.0,
  101.    4.0,-4.0, 0.0, 2.0, 2.0,-2.0,-0.5, 1.0, 1.5,-1.5,-0.5, 1.0,
  102.    1.5,-1.5,-0.5, 1.0, 1.0,-1.0,-0.5, 1.0, 2.0,-2.0, 0.0, 2.0,
  103.    0.0,-2.0, 0.0, 2.0, 0.0,-1.0, 0.5, 1.0, 0.0,-1.5, 0.5, 1.0,
  104.    0.0,-1.5, 0.5, 1.0, 0.0,-2.0, 0.5, 1.0, 0.0,-4.0, 0.0, 2.0,
  105.    0.0,-4.0, 0.0, 2.0, 0.0,-2.0,-0.5, 1.0, 0.0,-1.5,-0.5, 1.0,
  106.    0.0,-1.5,-0.5, 1.0, 0.0,-1.0,-0.5, 1.0, 0.0,-2.0, 0.0, 2.0,
  107.    0.0,-2.0, 0.0, 2.0, 0.0,-1.0, 0.5, 1.0, 0.0,-1.5, 0.5, 1.0,
  108.    0.0,-1.5, 0.5, 1.0, 0.0,-2.0, 0.5, 1.0, 0.0,-4.0, 0.0, 2.0,
  109.    0.0,-4.0, 0.0, 2.0, 0.0,-2.0,-0.5, 1.0, 0.0,-1.5,-0.5, 1.0,
  110.    0.0,-1.5,-0.5, 1.0, 0.0,-1.0,-0.5, 1.0, 0.0,-2.0, 0.0, 2.0,
  111.   -2.0,-2.0, 0.0, 2.0,-1.0,-1.0, 0.5, 1.0,-1.5,-1.5, 0.5, 1.0,
  112.   -1.5,-1.5, 0.5, 1.0,-2.0,-2.0, 0.5, 1.0,-4.0,-4.0, 0.0, 2.0,
  113.   -4.0,-4.0, 0.0, 2.0,-2.0,-2.0,-0.5, 1.0,-1.5,-1.5,-0.5, 1.0,
  114.   -1.5,-1.5,-0.5, 1.0,-1.0,-1.0,-0.5, 1.0,-2.0,-2.0, 0.0, 2.0,
  115.   -4.0, 0.0, 0.0, 4.0,-2.0, 0.0, 1.0, 2.0,-3.0, 0.0, 1.0, 2.0,
  116.   -3.0, 0.0, 1.0, 2.0,-4.0, 0.0, 1.0, 2.0,-8.0, 0.0, 0.0, 4.0,
  117.   -8.0, 0.0, 0.0, 4.0,-4.0, 0.0,-1.0, 2.0,-3.0, 0.0,-1.0, 2.0,
  118.   -3.0, 0.0,-1.0, 2.0,-2.0, 0.0,-1.0, 2.0,-4.0, 0.0, 0.0, 4.0,
  119.   -4.0, 0.0, 0.0, 4.0,-2.0, 0.0, 1.0, 2.0,-3.0, 0.0, 1.0, 2.0,
  120.   -3.0, 0.0, 1.0, 2.0,-4.0, 0.0, 1.0, 2.0,-8.0, 0.0, 0.0, 4.0,
  121.   -8.0, 0.0, 0.0, 4.0,-4.0, 0.0,-1.0, 2.0,-3.0, 0.0,-1.0, 2.0,
  122.   -3.0, 0.0,-1.0, 2.0,-2.0, 0.0,-1.0, 2.0,-4.0, 0.0, 0.0, 4.0,
  123.   -2.0, 2.0, 0.0, 2.0,-1.0, 1.0, 0.5, 1.0,-1.5, 1.5, 0.5, 1.0,
  124.   -1.5, 1.5, 0.5, 1.0,-2.0, 2.0, 0.5, 1.0,-4.0, 4.0, 0.0, 2.0,
  125.   -4.0, 4.0, 0.0, 2.0,-2.0, 2.0,-0.5, 1.0,-1.5, 1.5,-0.5, 1.0,
  126.   -1.5, 1.5,-0.5, 1.0,-1.0, 1.0,-0.5, 1.0,-2.0, 2.0, 0.0, 2.0,
  127.    0.0, 2.0, 0.0, 2.0, 0.0, 1.0, 0.5, 1.0, 0.0, 1.5, 0.5, 1.0,
  128.    0.0, 1.5, 0.5, 1.0, 0.0, 2.0, 0.5, 1.0, 0.0, 4.0, 0.0, 2.0,
  129.    0.0, 4.0, 0.0, 2.0, 0.0, 2.0,-0.5, 1.0, 0.0, 1.5,-0.5, 1.0,
  130.    0.0, 1.5,-0.5, 1.0, 0.0, 1.0,-0.5, 1.0, 0.0, 2.0, 0.0, 2.0,
  131.    0.0, 2.0, 0.0, 2.0, 0.0, 1.0, 0.5, 1.0, 0.0, 1.5, 0.5, 1.0,
  132.    0.0, 1.5, 0.5, 1.0, 0.0, 2.0, 0.5, 1.0, 0.0, 4.0, 0.0, 2.0,
  133.    0.0, 4.0, 0.0, 2.0, 0.0, 2.0,-0.5, 1.0, 0.0, 1.5,-0.5, 1.0,
  134.    0.0, 1.5,-0.5, 1.0, 0.0, 1.0,-0.5, 1.0, 0.0, 2.0, 0.0, 2.0,
  135.    2.0, 2.0, 0.0, 2.0, 1.0, 1.0, 0.5, 1.0, 1.5, 1.5, 0.5, 1.0,
  136.    1.5, 1.5, 0.5, 1.0, 2.0, 2.0, 0.5, 1.0, 4.0, 4.0, 0.0, 2.0,
  137.    4.0, 4.0, 0.0, 2.0, 2.0, 2.0,-0.5, 1.0, 1.5, 1.5,-0.5, 1.0,
  138.    1.5, 1.5,-0.5, 1.0, 1.0, 1.0,-0.5, 1.0, 2.0, 2.0, 0.0, 2.0,
  139.    4.0, 0.0, 0.0, 4.0, 2.0, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0,
  140.    3.0, 0.0, 1.0, 2.0, 4.0, 0.0, 1.0, 2.0, 8.0, 0.0, 0.0, 4.0,
  141.    8.0, 0.0, 0.0, 4.0, 4.0, 0.0,-1.0, 2.0, 3.0, 0.0,-1.0, 2.0,
  142.    3.0, 0.0,-1.0, 2.0, 2.0, 0.0,-1.0, 2.0, 4.0, 0.0, 0.0, 4.0,
  143. /* *INDENT-ON* */
  144.  
  145. };
  146.  
  147. /* Control points of a torus in NURBS form.  Can be rendered using
  148.    the GLU NURBS routines. */
  149. static GLfloat torusnurbpts[] =
  150. {
  151. /* *INDENT-OFF* */
  152.    4.0, 0.0, 0.0, 4.0, 2.0, 0.0, 1.0, 2.0, 4.0, 0.0, 1.0, 2.0,
  153.    8.0, 0.0, 0.0, 4.0, 4.0, 0.0,-1.0, 2.0, 2.0, 0.0,-1.0, 2.0,
  154.    4.0, 0.0, 0.0, 4.0, 2.0,-2.0, 0.0, 2.0, 1.0,-1.0, 0.5, 1.0,
  155.    2.0,-2.0, 0.5, 1.0, 4.0,-4.0, 0.0, 2.0, 2.0,-2.0,-0.5, 1.0,
  156.    1.0,-1.0,-0.5, 1.0, 2.0,-2.0, 0.0, 2.0,-2.0,-2.0, 0.0, 2.0,
  157.   -1.0,-1.0, 0.5, 1.0,-2.0,-2.0, 0.5, 1.0,-4.0,-4.0, 0.0, 2.0,
  158.   -2.0,-2.0,-0.5, 1.0,-1.0,-1.0,-0.5, 1.0,-2.0,-2.0, 0.0, 2.0,
  159.   -4.0, 0.0, 0.0, 4.0,-2.0, 0.0, 1.0, 2.0,-4.0, 0.0, 1.0, 2.0,
  160.   -8.0, 0.0, 0.0, 4.0,-4.0, 0.0,-1.0, 2.0,-2.0, 0.0,-1.0, 2.0,
  161.   -4.0, 0.0, 0.0, 4.0,-2.0, 2.0, 0.0, 2.0,-1.0, 1.0, 0.5, 1.0,
  162.   -2.0, 2.0, 0.5, 1.0,-4.0, 4.0, 0.0, 2.0,-2.0, 2.0,-0.5, 1.0,
  163.   -1.0, 1.0,-0.5, 1.0,-2.0, 2.0, 0.0, 2.0, 2.0, 2.0, 0.0, 2.0,
  164.    1.0, 1.0, 0.5, 1.0, 2.0, 2.0, 0.5, 1.0, 4.0, 4.0, 0.0, 2.0,
  165.    2.0, 2.0,-0.5, 1.0, 1.0, 1.0,-0.5, 1.0, 2.0, 2.0, 0.0, 2.0,
  166.    4.0, 0.0, 0.0, 4.0, 2.0, 0.0, 1.0, 2.0, 4.0, 0.0, 1.0, 2.0,
  167.    8.0, 0.0, 0.0, 4.0, 4.0, 0.0,-1.0, 2.0, 2.0, 0.0,-1.0, 2.0,
  168.    4.0, 0.0, 0.0, 4.0,
  169. /* *INDENT-ON* */
  170.  
  171. };
  172.  
  173. void 
  174. move(int x, int y)
  175. {
  176.   prevx = curx;
  177.   prevy = cury;
  178.   curx = x;
  179.   cury = y;
  180.   if (curx != startx || cury != starty) {
  181.     glutPostRedisplay();
  182.     startx = curx;
  183.     starty = cury;
  184.   }
  185. }
  186.  
  187. void 
  188. button(int button, int state, int x, int y)
  189. {
  190.   if (button != GLUT_LEFT_BUTTON)
  191.     return;
  192.   switch (state) {
  193.   case GLUT_DOWN:
  194.     prevx = curx = startx = x;
  195.     prevy = cury = starty = y;
  196.     spindx = 0;
  197.     spindy = 0;
  198.     tracking = GL_TRUE;
  199.     break;
  200.   case GLUT_UP:
  201.     /* 
  202.      * If user released the button while moving the mouse, keep
  203.      * spinning.
  204.      */
  205.     if (x != prevx || y != prevy) {
  206.       spindx = x - prevx;
  207.       spindy = y - prevy;
  208.     }
  209.     tracking = GL_FALSE;
  210.     break;
  211.   }
  212. }
  213.  
  214. /* Maintain a square window when resizing */
  215. void 
  216. reshape(int width, int height)
  217. {
  218.   int size;
  219.   size = (width < height ? width : height);
  220.   glViewport((width - size) / 2, (height - size) / 2, size, size);
  221.   glutReshapeWindow(size, size);
  222.   glutPostRedisplay();
  223. }
  224.  
  225. void 
  226. gridmaterials(void)
  227. {
  228.   static float front_mat_diffuse[] =
  229.   {1.0, 1.0, 0.4, 1.0};
  230.   static float front_mat_ambient[] =
  231.   {0.1, 0.1, 0.1, 1.0};
  232.   static float back_mat_diffuse[] =
  233.   {1.0, 0.0, 0.0, 1.0};
  234.   static float back_mat_ambient[] =
  235.   {0.1, 0.1, 0.1, 1.0};
  236.  
  237.   glMaterialfv(GL_FRONT, GL_DIFFUSE, front_mat_diffuse);
  238.   glMaterialfv(GL_FRONT, GL_AMBIENT, front_mat_ambient);
  239.   glMaterialfv(GL_BACK, GL_DIFFUSE, back_mat_diffuse);
  240.   glMaterialfv(GL_BACK, GL_AMBIENT, back_mat_ambient);
  241. }
  242.  
  243. void 
  244. surfacematerials(void)
  245. {
  246.   static float front_mat_diffuse[] =
  247.   {0.2, 0.7, 0.4, 1.0};
  248.   static float front_mat_ambient[] =
  249.   {0.1, 0.1, 0.1, 1.0};
  250.   static float back_mat_diffuse[] =
  251.   {1.0, 1.0, 0.2, 1.0};
  252.   static float back_mat_ambient[] =
  253.   {0.1, 0.1, 0.1, 1.0};
  254.  
  255.   glMaterialfv(GL_FRONT, GL_DIFFUSE, front_mat_diffuse);
  256.   glMaterialfv(GL_FRONT, GL_AMBIENT, front_mat_ambient);
  257.   glMaterialfv(GL_BACK, GL_DIFFUSE, back_mat_diffuse);
  258.   glMaterialfv(GL_BACK, GL_AMBIENT, back_mat_ambient);
  259. }
  260.  
  261. void 
  262. init(void)
  263. {
  264.   static float ambient[] =
  265.   {0.0, 0.0, 0.0, 1.0};
  266.   static float diffuse[] =
  267.   {1.0, 1.0, 1.0, 1.0};
  268.   static float position[] =
  269.   {90.0, 90.0, -150.0, 0.0};
  270.   static float lmodel_ambient[] =
  271.   {1.0, 1.0, 1.0, 1.0};
  272.   static float lmodel_twoside[] =
  273.   {GL_TRUE};
  274.  
  275.   glMatrixMode(GL_PROJECTION);
  276.   glLoadIdentity();
  277.   gluPerspective(40.0, 1.0, 2.0, 200.0);
  278.   glMatrixMode(GL_MODELVIEW);
  279.   glLoadIdentity();
  280.   glGetFloatv(GL_MODELVIEW_MATRIX, modelmatrix);
  281.  
  282.   glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
  283.   glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
  284.   glLightfv(GL_LIGHT0, GL_POSITION, position);
  285.   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
  286.  
  287.   glEnable(GL_LIGHTING);
  288.   glEnable(GL_LIGHT0);
  289.   glEnable(GL_DEPTH_TEST);
  290.   glEnable(GL_AUTO_NORMAL);
  291.   glFrontFace(GL_CCW);
  292.  
  293.   glEnable(GL_MAP2_VERTEX_4);
  294.   glClearColor(0.25, 0.25, 0.5, 0.0);
  295.  
  296. #if GL_EXT_polygon_offset
  297.   glPolygonOffsetEXT(factor, bias);
  298.   glEnable(GL_POLYGON_OFFSET_EXT);
  299. #endif
  300.  
  301.   nobj = gluNewNurbsRenderer();
  302. #ifdef GLU_VERSION_1_1  /* New GLU 1.1 interface. */
  303.   gluNurbsProperty(nobj, GLU_SAMPLING_METHOD, GLU_DOMAIN_DISTANCE);
  304. #endif
  305.  
  306.   surflist = glGenLists(1);
  307.   gridlist = glGenLists(1);
  308.   createlists();
  309. }
  310.  
  311. void 
  312. drawmesh(void)
  313. {
  314.   int i, j;
  315.   float *p;
  316.  
  317.   int up2p = 4;
  318.   int uorder = 3, vorder = 3;
  319.   int nu = 4, nv = 4;
  320.   int vp2p = up2p * uorder * nu;
  321.  
  322.   for (j = 0; j < nv; j++) {
  323.     for (i = 0; i < nu; i++) {
  324.       p = torusbezierpts + (j * vp2p * vorder) + (i * up2p * uorder);
  325. #if GL_EXT_polygon_offset
  326.       glPolygonOffsetEXT(factor, bias);
  327. #endif
  328.       glMap2f(GL_MAP2_VERTEX_4, 0.0, 1.0, up2p, 3, 0.0, 1.0, vp2p, 3,
  329.         (void *) p);
  330.       if (showsurf) {
  331.         surfacematerials();
  332.         glEvalMesh2(GL_FILL, 0, usegments, 0, vsegments);
  333.       }
  334.       if (showgrid) {
  335.         gridmaterials();
  336.         glEvalMesh2(GL_LINE, 0, usegments, 0, vsegments);
  337.       }
  338.     }
  339.   }
  340. }
  341.  
  342. void 
  343. redraw(void)
  344. {
  345.   int dx, dy;
  346.   float v[3], rot[3];
  347.   float len, ang;
  348.   static GLuint vcount;
  349.  
  350.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  351.   glColor3f(1, 0, 0);
  352.  
  353.   if (tracking) {
  354.     dx = curx - startx;
  355.     dy = cury - starty;
  356.   } else {
  357.     dx = spindx;
  358.     dy = spindy;
  359.   }
  360.   if (dx || dy) {
  361.     dy = -dy;
  362.     v[0] = dx;
  363.     v[1] = dy;
  364.     v[2] = 0;
  365.  
  366.     len = length(v);
  367.     ang = -len / 600 * 360;
  368.     norm(v);
  369.     cross(v, z_axis, rot);
  370.  
  371.     /* This is certainly not recommended for programs that care
  372.        about performance or numerical stability: we concatenate
  373.        the rotation onto the current modelview matrix and read
  374.        the matrix back, thus saving ourselves from writing our
  375.        own matrix manipulation routines.  */
  376.     glLoadIdentity();
  377.     glRotatef(ang, rot[0], rot[1], rot[2]);
  378.     glMultMatrixf(modelmatrix);
  379.     glGetFloatv(GL_MODELVIEW_MATRIX, modelmatrix);
  380.   }
  381.   glLoadIdentity();
  382.   glTranslatef(0.0, 0.0, -10.0);
  383.   glMultMatrixf(modelmatrix);
  384.  
  385.   if (useglunurbs) {
  386.     if (showsurf)
  387.       glCallList(surflist);
  388.     if (showgrid)
  389.       glCallList(gridlist);
  390.   } else {
  391.     glMapGrid2f(usegments, 0.0, 1.0, vsegments, 0.0, 1.0);
  392.     drawmesh();
  393.   }
  394.  
  395.   glutSwapBuffers();
  396. }
  397.  
  398. static void 
  399. usage(void)
  400. {
  401.   printf("usage: surfgrid [-f]\n");
  402.   exit(-1);
  403. }
  404.  
  405. /* what to do when a menu item is selected. This function also handles
  406.    keystroke events.  */
  407. void 
  408. menu(int item)
  409. {
  410.   switch (item) {
  411.   case 'p':
  412. #if GL_EXT_polygon_offset
  413.     if (glIsEnabled(GL_POLYGON_OFFSET_EXT)) {
  414.       glDisable(GL_POLYGON_OFFSET_EXT);
  415.       printf("disabling polygon offset\n");
  416.     } else {
  417.       glEnable(GL_POLYGON_OFFSET_EXT);
  418.       printf("enabling polygon offset\n");
  419.     }
  420. #endif
  421.     break;
  422.   case 'F':
  423.     factor += 0.1;
  424.     printf("factor: %8.4f\n", factor);
  425.     break;
  426.   case 'f':
  427.     factor -= 0.1;
  428.     printf("factor: %8.4f\n", factor);
  429.     break;
  430.   case 'B':
  431.     bias += 0.0001;
  432.     printf("bias:  %8.4f\n", bias);
  433.     break;
  434.   case 'b':
  435.     bias -= 0.0001;
  436.     printf("bias:  %8.4f\n", bias);
  437.     break;
  438.   case 'g':
  439.     showgrid = !showgrid;
  440.     break;
  441.   case 'n':
  442.     useglunurbs = !useglunurbs;
  443.     break;
  444.   case 's':
  445.     smooth = !smooth;
  446.     if (smooth) {
  447.       glShadeModel(GL_SMOOTH);
  448.     } else {
  449.       glShadeModel(GL_FLAT);
  450.     }
  451.     break;
  452.   case 't':
  453.     showsurf = !showsurf;
  454.     break;
  455.   case 'u':
  456.     usegments = (usegments < 2 ? 1 : usegments - 1);
  457.     createlists();
  458.     break;
  459.   case 'U':
  460.     usegments++;
  461.     createlists();
  462.     break;
  463.   case 'v':
  464.     vsegments = (vsegments < 2 ? 1 : vsegments - 1);
  465.     createlists();
  466.     break;
  467.   case 'V':
  468.     vsegments++;
  469.     createlists();
  470.     break;
  471.   case '\033':         /* ESC key: quit */
  472.     exit(0);
  473.     break;
  474.   }
  475.   glutPostRedisplay();
  476. }
  477.  
  478. void 
  479. key(unsigned char key, int x, int y)
  480. {
  481.   menu((int) key);
  482. }
  483.  
  484. void 
  485. animate(void)
  486. {
  487.   if (!tracking && (spindx != 0 || spindy != 0))
  488.     glutPostRedisplay();
  489. }
  490.  
  491. int
  492. main(int argc, char **argv)
  493. {
  494.   int i;
  495.  
  496.   glutInit(&argc, argv);  /* initialize glut, processing
  497.                              arguments */
  498.  
  499.   for (i = 1; i < argc; i++) {
  500.     if (argv[i][0] == '-') {
  501.       switch (argv[i][1]) {
  502.       case 'f':
  503.         fullscreen = 1;
  504.         break;
  505.       default:
  506.         usage();
  507.         break;
  508.       }
  509.     } else {
  510.       usage();
  511.     }
  512.   }
  513.  
  514.   glutInitWindowSize(winwidth, winheight);
  515.   glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
  516.   glutCreateWindow("surfgrid");
  517.  
  518.   /* create a menu for the right mouse button */
  519.   glutCreateMenu(menu);
  520. #if GL_EXT_polygon_offset
  521.   glutAddMenuEntry("p: toggle polygon offset", 'p');
  522. #endif
  523.   glutAddMenuEntry("F: increase factor", 'F');
  524.   glutAddMenuEntry("f: decrease factor", 'f');
  525.   glutAddMenuEntry("B: increase bias", 'B');
  526.   glutAddMenuEntry("b: decrease bias", 'b');
  527.   glutAddMenuEntry("g: toggle grid", 'g');
  528.   glutAddMenuEntry("s: toggle smooth shading", 's');
  529.   glutAddMenuEntry("t: toggle surface", 't');
  530.   glutAddMenuEntry("n: toggle GL evalutators/GLU nurbs", 'n');
  531.   glutAddMenuEntry("u: decrement u segments", 'u');
  532.   glutAddMenuEntry("U: increment u segments", 'U');
  533.   glutAddMenuEntry("v: decrement v segments", 'v');
  534.   glutAddMenuEntry("V: increment v segments", 'V');
  535.   glutAddMenuEntry("<esc>: exit program", '\033');
  536.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  537.  
  538.   /* set callbacks */
  539.   glutKeyboardFunc(key);
  540.   glutDisplayFunc(redraw);
  541.   glutReshapeFunc(reshape);
  542.   glutMouseFunc(button);
  543.   glutMotionFunc(move);
  544.   glutIdleFunc(animate);
  545.  
  546. #if GL_EXT_polygon_offset
  547.   if (!glutExtensionSupported("GL_EXT_polygon_offset")) {
  548.     printf("Warning: "
  549.       "GL_EXT_polygon_offset not supported on this machine... "
  550.       "trying anyway\n");
  551.   }
  552. #else
  553.   printf("Warning: not compiled with GL_EXT_polygon_offset support.\n");
  554. #endif
  555.  
  556.   init();
  557.   glutMainLoop();
  558.   return 0;             /* ANSI C requires main to return int. */
  559. }
  560.  
  561. float circleknots[] =
  562. {0.0, 0.0, 0.0, 0.25, 0.50, 0.50, 0.75, 1.0, 1.0, 1.0};
  563.  
  564. void 
  565. createlists(void)
  566. {
  567. #ifdef GLU_VERSION_1_1  /* New GLU 1.1 interface. */
  568.   gluNurbsProperty(nobj, GLU_U_STEP, (usegments - 1) * 4);
  569.   gluNurbsProperty(nobj, GLU_V_STEP, (vsegments - 1) * 4);
  570.  
  571.   gluNurbsProperty(nobj, GLU_DISPLAY_MODE, GLU_FILL);
  572. #endif
  573.   glNewList(surflist, GL_COMPILE);
  574.   surfacematerials();
  575.   gluBeginSurface(nobj);
  576.   gluNurbsSurface(nobj, 10, circleknots, 10, circleknots,
  577.     4, 28, torusnurbpts, 3, 3, GL_MAP2_VERTEX_4);
  578.   gluEndSurface(nobj);
  579.   glEndList();
  580.  
  581.   gluNurbsProperty(nobj, GLU_DISPLAY_MODE, GLU_OUTLINE_POLYGON);
  582.   glNewList(gridlist, GL_COMPILE);
  583.   gridmaterials();
  584.   gluBeginSurface(nobj);
  585.   gluNurbsSurface(nobj, 10, circleknots, 10, circleknots,
  586.     4, 28, torusnurbpts, 3, 3, GL_MAP2_VERTEX_4);
  587.   gluEndSurface(nobj);
  588.   glEndList();
  589. }
  590.  
  591.